const Flow = require("./Flow/Flow");
const CardBox = require("./Flow/CardBox");
const Player = require("./Flow/Player");
const Room = require("./Flow/Room");
const Card = require("./Flow/Card");
const rule = require("./Flow/rule");
const Queue = require("./Flow/Queue");
const { User } = require("./router/admin");
const caw = require("caw");
const https = require("https");

const {
	redis_client,
	redis_prefix,
	md5,
	db,
	on,
	successRes,
	errorRes,
	adminEvents,
	sleep
} = require("./unit");
const pingModule = require("ping");

const ADMIN_IO_SOCKET_WM = new WeakMap();
const { CUSTOME_CARDBOX_GENERATOR_MAP } = Flow;

const pingAgent = caw("http://127.0.0.1:8118", {
	protocol: "https"
});
// 监测与firebase的连接情况
/*const connect_info = {
	is_connect: false,
	start_time: 0,
	end_time: 0,
	lock: false,
	_ping: 0,
	get ping() {
		if (this.lock) {
			return this._ping;
		} else {
			this.lock = true;
			this.end_time = Date.now();
			return (this._ping = this.end_time - this.start_time);
		}
	},
	cur_ping: null,
	toJSON() {
		return {
			is_connect: connect_info.is_connect,
			ping: connect_info.ping
		};
	}
};*/
(function() {
	const connect_info = {
		ping: 0,
		is_connect: false,
		cur_ping: null,
		toJSON() {
			return {
				is_connect: this.is_connect,
				ping: this.ping
			};
		}
	};

	async function ping_db_server() {
		const ping_info = await pingModule.promise.probe(
			"shui-35c19.firebaseio.com"
		);
		connect_info.is_connect = ping_info.alive;

		const ping = (connect_info.ping = ping_info.time);
		if (ping < 1000) {
			await sleep(1000 - ping);
		}
		return ping;
	}
	function ping_chain() {
		connect_info.cur_ping.then(() => {
			adminEvents.emit("ping-firebase", connect_info);
			connect_info.cur_ping = ping_db_server();
			connect_info.cur_ping.then(ping_chain);
		});
	}
	// 开始PING
	connect_info.cur_ping = ping_db_server();
	ping_chain();
})();

/* 记录游戏在线人数 */
let cur_online_player_number = 0;
adminEvents.on("online-player-number-changed", online_player_number => {
	cur_online_player_number = online_player_number;
});
/* 监控在线房间信息 */
let cur_online_room_number = 0;
const { ROOM_MAP } = Room;
adminEvents.on("online-room-number-changed", online_room_number => {
	cur_online_room_number = online_room_number;
});

exports.setup = function(socket) {
	on(socket, "admin-login", async data => {
		const { admin_io_token } = data;
		const ADMIN_IO_TOKEN = await redis_client.getAsync(
			redis_prefix + "ADMIN-IO-TOKEN"
		);
		const login_success = ADMIN_IO_TOKEN === admin_io_token;
		if (login_success) {
			installAdminSocket(socket);
		}
		socket.emit("admin-login-result", login_success);
	});
	on(socket, "disconnect", function() {
		if (ADMIN_IO_SOCKET_WM.has(socket)) {
			const admin_io_info = ADMIN_IO_SOCKET_WM.get(socket);
			ADMIN_IO_SOCKET_WM.delete(socket);
		}
	});
};
function installAdminSocket(socket) {
	const admin_io_info = {};
	ADMIN_IO_SOCKET_WM.set(socket, admin_io_info);

	adminEvents.on("ping-firebase", connect_info => {
		socket.emit("firebase-ping-result", connect_info.toJSON());
	});

	/*在线用户人数*/
	function on_online_player_number_changed() {
		socket.emit("online-player-number", cur_online_player_number);
	}
	adminEvents.on(
		"online-player-number-changed",
		on_online_player_number_changed
	);
	socket.on("online-player-number", on_online_player_number_changed);

	const watchd_room_id_map = new Map();
	/*在线房间信息*/
	socket.on("online-room-info", page_info => {
		if (!page_info) {
			return;
		}
		const { page, num, auto_watch } = page_info;
		const _page = parseInt(page, 10) || 1;
		const _num = parseInt(num, 10) || 10;
		const room_list = [];

		let from = (_page - 1) * _num;
		let to = _page * _num;
		let i = 0;
		for (let room of ROOM_MAP.values()) {
			if (i >= from) {
				if (i >= to) {
					break;
				}
				room_list.push(room);
			}
			i += 1;
		}
		const rooms_info = {
			total: cur_online_room_number,
			page: _page,
			num: _num,
			list: room_list
		};
		if (auto_watch) {
			// 添加到监听列表中
			watch_room_id_list(room_list.map(room => room.id));
		}
		socket.emit("online-room-info-result", rooms_info);
	});
	adminEvents.on("online-room-number-changed", () => {
		socket.emit("online-room-number", cur_online_room_number);
	});
	// 提交需要监听变动的房间号ID
	function watch_room_id_list(watchd_room_id_list) {
		watchd_room_id_map.clear();
		watchd_room_id_list.forEach(room_id =>
			watchd_room_id_map.set(room_id, true)
		);
	}
	socket.on("watchd-room-id-list", watch_room_id_list);
	adminEvents.on("online-room-changed", room => {
		if (watchd_room_id_map.has(room.id)) {
			socket.emit("room-changed", room);
		}
	});
	// 串改指定房间某一回合的牌组
	socket.on("--cheat-flow-cards--", data => {
		const {
			room_id,
			player_id_customs_cards_index_map,
			custom_cards_list,
			flow_id
		} = data;
		CUSTOME_CARDBOX_GENERATOR_MAP.set(flow_id, player_list => {
			try {
				const CARDBOX = new CardBox();
				console.log("CHEAT MAP:", player_id_customs_cards_index_map);
				const res_index_cards_map = {};
				player_list.forEach((player, player_index) => {
					console.log(player.id, player.info.nickname);
					const customs_cards_index =
						player_id_customs_cards_index_map[player.id];
					if (
						customs_cards_index === false ||
						!isFinite(customs_cards_index)
					) {
						return;
					}
					const custom_cards = custom_cards_list[customs_cards_index];
					console.log("CHEAT TARGET:", custom_cards.join());
					const custom_cards_ins = custom_cards
						.map((card_txt, i) => {
							if (!card_txt) {
								console.error("CHEAT异常: card_txt", card_txt);
								return;
							}
							const card = Card.getIns(card_txt);
							if (!card) {
								console.error("CHEAT异常: card为空", card);
								return;
							}
							const old_index = CARDBOX.card_list.indexOf(card);
							if (old_index === -1) {
								console.error(
									"CHEAT异常: old_index找不到",
									old_index
								);
								return;
							}
							CARDBOX.card_list.splice(old_index, 1);
							return card;
						})
						.filter(card => card);
					res_index_cards_map[player_index] = custom_cards_ins;
				});
				for (let i = 0, len = player_list.length; i < len; i += 1) {
					if (res_index_cards_map[i]) {
						const base_index = 13 * i;
						CARDBOX.card_list.splice(
							base_index,
							0,
							...res_index_cards_map[i]
						);
					}
				}
				console.log("CHEAT RESULT");
				console.log(
					CARDBOX.card_list
						.map((c, i) => {
							if (i % 13 == 0 && i != 0) {
								return c.toString() + "\n";
							}
							return c.toString() + ", ";
						})
						.join("")
				);
				CUSTOME_CARDBOX_GENERATOR_MAP.delete(flow_id);
				return CARDBOX;
			} catch (e) {
				console.error("CHEAT ERROR", e);
				CUSTOME_CARDBOX_GENERATOR_MAP.delete(flow_id);
				return new CardBox();
			}
		});
		socket.emit("--cheat-flow-cards-result--");

		const [flow_id_symbol, flow_id_hash] = flow_id.split("|");
		const flow_id_prefix = flow_id_symbol + "|" + flow_id_hash + "|";
		console.log(flow_id_prefix);
		getCheatFlowsByFlowIdPrefix(flow_id_prefix);
	});
	function getCheatFlowsByFlowIdPrefix(flow_id_prefix) {
		const res = new Set();
		for (let flow_id of CUSTOME_CARDBOX_GENERATOR_MAP.keys()) {
			if (flow_id.startsWith(flow_id_prefix)) {
				const round_index = flow_id.substr(flow_id_prefix.length);
				if (isFinite(round_index)) {
					res.add(round_index | 0);
				}
			}
		}
		socket.emit("--cheat-room-flows-result--", [...res.values()]);
	}
	socket.on("--cheat-room-flows--", data => {
		const { flow_id_prefix } = data;
		if (flow_id_prefix) {
			getCheatFlowsByFlowIdPrefix(flow_id_prefix);
		}
	});
}
